<template>
  <div>
    <el-switch v-model="draggable" active-text="开启拖拽" inactive-text="关闭拖拽"></el-switch>
    <!-- 如果draggable=true（打开拖拽）时，显示批量更新按钮 -->
     <el-button type="primary" v-if="draggable" @click="updateSort" >批量更新</el-button>
     <el-button type="danger" @click="bacthDelete" >批量删除</el-button>

    <el-tree :data="data" :props="defaultProps"  :expand-on-click-node="false" show-checkbox node-key="catId"
     :default-expanded-keys=expandKeys :draggable="true"  :allow-drop="allowDrop" @node-drop="handleDrop"
     ref="tree" 
     >
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button v-if="data.catLevel <= 2" type="text"  size="mini" @click="() => append(data)"> 添加</el-button>
           <el-button type="text"  size="mini" @click="() => edit(data)"> 更新</el-button>
          <el-button 
            v-if="data.childrens && data.childrens.length == 0" 
            type="text" size="mini"  
            @click="() => remove(node, data)">删除</el-button>
        </span>
      </span>
    </el-tree>

    <!-- 添加的弹出框 -->
     <el-dialog :title="dialogType?'新增':'更新'" :visible.sync="dialogVisible" width="30%" :close-on-click-modal= "false">
      <!-- 添加表单 -->
      <el-form :model="categoryFrom">
        <el-form-item label="类目名称" >
          <el-input v-model="categoryFrom.name" autocomplete="off"></el-input>
        </el-form-item>
         <el-form-item label="图标" >
          <el-input v-model="categoryFrom.icon" autocomplete="off"></el-input>
        </el-form-item>
         <el-form-item label="计量单位" >
          <el-input v-model="categoryFrom.productUnit" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitForm">确 定</el-button>
      </span>
    </el-dialog>

  </div>
</template>

<script>
 /* eslint-disable */
export default {
    data() {
      return {
        pCids:[],//拖拽后的父节点数组
        draggable: false,//默认拖拽功能关闭
        updateNode:[],//拖拽节点后，需要更新的节点的节点信息
        maxLevel:0,//最大级别
        dialogType:false, // true:添加  false:更新s
        dialogVisible:false,//默认不打开，点击时打开
        categoryFrom:{name:null,icon:null,productUnit:null,showStatus:1,sort:0,catLevel:1},//类目表单对象
        data: [],
        expandKeys:[],
        defaultProps: {
          children: 'childrens',
          label: 'name'
        }
      };
    },
    /*写操作方法的 */
    methods: {
    /**获取三级分类列表 */
    getCatagory(){
        this.$http({
          url: this.$http.adornUrl('/product/category/listTree'),
          method: 'get',
          params: this.$http.adornParams()
        }).then(({data}) => {
          console.log("成功获取的类别数据：",data.data)
          this.data = data.data
        })
    },
      //添加
      append(data) {
        this.dialogVisible=true;//点击时，设置dialogVisible为true,就打开弹框
        console.log("添加",data);

        //添加的类目，逻辑初始化
        this.categoryFrom.parentCid = data.catId;//添加的id，是点击的类目id下
        this.categoryFrom.catLevel = data.catLevel + 1;//对应的层级 = 当前类目的层级+1
        this.categoryFrom.showStatus = 1;  //默认显示
        this.categoryFrom.sort = 0;

        //重置更新的数据
        this.categoryFrom.catId=null;
        this.categoryFrom.name="";
        this.categoryFrom.productUnit="";
        this.categoryFrom.icon="";
      
        //更新状态
        this.dialogType=true;//表示更新

      },  
        //批量删除
        bacthDelete(){
          let catIds = [];
          //true：节点可被选择，则返回目前被选中的节点所组成的数组.\.
          //接收两个 boolean 类型的参数，1. 是否只是叶子节点，默认值为 false 2. 是否包含半选节点，默认值为 false
          let checkedNodes= this.$refs.tree.getCheckedNodes(false, false);
          
          // console.log("--->",checkedNodes)  //选择节点，点击批量删除后，后台有数据
          for(let i = 0; i < checkedNodes.length ; i++ ){
            catIds.push(checkedNodes[i].catId);
          }
          //删除确认
          this.$confirm(`是否确认删除【${catIds}】?`, '提示', {
             confirmButtonText: '确定',
             cancelButtonText: '取消',
             type: 'warning'
          }).then(() => {
            // 把删除的请求提交到后台服务
            this.$http({
                url: this.$http.adornUrl("/product/category/logicDelete"),
                method: "post",
                data: this.$http.adornData(catIds, false),
            }).then(({ data }) => {
                if (data && data.code === 0) {
                     this.$message({
                        message: "操作成功",
                        type: "success",
                     });
                     // 重新加载所有的菜单数据
                     this.getCatagory();
                 } else {
                    this.$message.error(data.msg);
                 }
           });
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
      },

       //拖拽节点后，数据的更新处理
       handleDrop(draggingNode, dropNode, type) {
        //console.log('tree drop: ', dropNode.label, dropType);
        //1、拖拽节点的父节点
        let parentId = 0;
        
        // 找到拖拽节点对应的所有的兄弟节点
        let siblings = null;
        if(type == 'inner'){ //如果当前的节点 = 目标节点的内部   就是目标节点的值
          parentId = dropNode.data.catId;
          siblings = dropNode.childNodes;//找到拖拽节点对应的所有的兄弟节点
        }else{
          // 否则，当前dropNode节点的父节点，作为父节点(有一种情况是在第一级目录，没有父节点了，要判断)
          parentId = dropNode.parent.data.catId == undefined ? 0 : dropNode.parent.data.catId ; 
          siblings = dropNode.parent.childNodes;
        }

        //2、拖拽后，节点所在的新的兄弟节点的排序问题
        for(let i = 0; i < siblings.length ; i++){
            //如果拖拽的节点id = 获取的那个节点，就需要更新parent_cid
            if(siblings[i].data.catId == draggingNode.data.catId){

              //3、拖拽后的节点及其子节点的层级更新问题
              let catLevel = draggingNode.level;//记录拖拽后的节点层级
              if(siblings[i].level != catLevel ){ //不相等--说明拖拽移动后，节点的层级发生了变化
                 
                 catLevel = siblings[i].level;//本身的拖拽后的层级 = 遍历出来节点的层级

                  //递归方式——遍历更新出子节点的层级level
                  this.updateChildNodeLevel(siblings[i]);
              }
                this.updateNode.push({ 
                  catId: siblings[i].data.catId, 
                  sort: i, 
                  parentCid: parentId,
                  catLevel: catLevel
                });
            }else{
              //排序需要把每个节点updateNode节点信息更新到数据库，因此， 需要搜集updateNode信息
              this.updateNode.push({
                catId: siblings[i].data.catId, 
                sort: i
              });
            }
        }

         //4、将拖拽后的数据，完整的提交到后端
         //console.log("handleDrop-拖拽数据----->",this.updateNode);
         //this.updateSort(parentId);

         this.pCids.push(this.parentId);

       },
       updateSort(parentId){
          //批量更新 拖拽后的数据（层级+排序）
         this.$http({
            url: this.$http.adornUrl("/product/category/updateBatch"),//请求的地址
            method: "post",
            data: this.$http.adornData(this.updateNode, false),//提交的数据
          }).then(({ data }) => {
            if (data && data.code === 0) {
                this.$message({
                  message: "拖拽操作成功",
                  type: "success",
                });
                // 重新加载所有的菜单数据
                this.getCatagory();
                // 设置默认展开的父节点信息
                this.expandKeys = this.pCids

                // 重置存储拖拽数据的容器
                this.updateNode = [];
                this.maxLevel = 0;

              } else {
                this.$message.error(data.msg);
              }
          });
       },
       
       // 递归方式——遍历更新出子节点的层级level
       updateChildNodeLevel(node){
        if(node.childNodes != null && node.childNodes.length > 0){
          for(let i = 0; i< node.childNodes.length ; i++){
            //记录当前子节点下的节点
            var childNode = node.childNodes[i].data;
            //更新所有子节点的层级
            this.updateNode.push({
              catId: node.childNodes.catId, 
              catLevel: node.childNodes[i].level
            });
            
            //如果还有子节点，同步更新处理
            this.updateChildNodeLevel(node.childNodes[i]);
          }
        }
       },

      //判断拖拽的节点，是否可以放在该位置
        // draggingNode 要拖拽的节点
        // dropNode 目标节点
        // type 参数有三种情况：'prev'、'inner' 和 'next'
      allowDrop(draggingNode, dropNode, type){
       // console.log("allowDrop:" + draggingNode, dropNode, type)
       
        //1、获取当前被拖拽节点的最大level（层级）
        this.catNodeLevel(draggingNode);

        //得到最大深度（绝对值）
        let deep = Math.abs(this.maxLevel - draggingNode.level) + 1;

       // console.log("allowDrop-->maxLevel：" + this.maxLevel,"level："+draggingNode.level,"deep:"+deep);

        //要放在的位置-判断
         if(type == 'inner'){
             //深度+ 要移动的层级  
             return deep + dropNode.level <= 3;
         }
        //放在它的前后 
         return deep + dropNode.parent.level <= 3;
      },

      //获取当前被拖拽节点的最大level（层级）
       catNodeLevel(node){
        //在查找拖拽节点的子节点的最大level,先赋值
        this.maxLevel = node.data.catLevel;

        //找到所有的子节点，最大的level
        if(node.childNodes != null && node.childNodes.length > 0){
          for(let i = 0; i < node.childNodes.length; i ++){
              if(node.childNodes[i].level > this.maxLevel){
                this.maxLevel = node.childNodes[i].level;
              }
                this.catNodeLevel(node.childNodes[i]);//有可能有很多子节点，递归。
            }
         }
       },  

      //添加商品三级类目的类目信息
      adddialog(){
        this.$http({
              url: this.$http.adornUrl("/product/category/save"),//请求的地址
              method: "post",
              data: this.$http.adornData(this.categoryFrom, false),//提交的数据
          }).then(({ data }) => {
              if (data && data.code === 0) {
                    this.$message({
                      message: "添加类目成功",
                      type: "success",
                    });
                    this.dialogVisible = false;//关闭窗口

                    // 重新加载所有的菜单数据
                    this.getCatagory();

                    // 设置默认展开的父节点信息
                    this.expandKeys=[this.categoryFrom.parentCid]
                } else {
                  this.$message.error(data.msg);
                }
          });
      },
      //点击确认后，更新数据到数据库
      editdialog(){
        this.$http({
            url: this.$http.adornUrl("/product/category/update"),//请求的地址
            method: "post",
            data: this.$http.adornData(this.categoryFrom, false),//提交的数据
          }).then(({ data }) => {
            if (data && data.code === 0) {
                this.$message({
                  message: "数据更新成功",
                  type: "success",
                });
                this.dialogVisible = false;//关闭窗口

                // 重新加载所有的菜单数据
                this.getCatagory();

                // 设置默认展开的父节点信息
                this.expandKeys=[this.categoryFrom.parentCid]
              } else {
                this.$message.error(data.msg);
              }
          });
      },
      //点击确认，提交表单
      submitForm(){
        //判断当前操作是添加，还是更新
        if(this.dialogType){
          this.adddialog();//添加操作
        }else{
          this.editdialog();//更新操作
        }
      },

        //添加更新，弹出表单的回显问题
        edit(data){
          this.dialogType=false;//表示更新
          //获取最新的数据，进行回写
          this.$http({
            url: this.$http.adornUrl(`/product/category/info/${data.catId}`), //请求的地址
            method: "post",
            data: this.$http.adornData(this.categoryFrom, false),//提交的数据
        }).then(({data}) => {
              //表单数据回显
            this.categoryFrom.name =data.category.name;
            this.categoryFrom.productUnit =data.category.productUnit;
            this.categoryFrom.icon =data.category.icon;
            this.categoryFrom.catLevel = data.category.catLevel;
            this.categoryFrom.parentCid = data.category.parentCid;

            //更新填充常规的数据（更新常规信息，不然数据会清空）
            this.categoryFrom.catId = data.category.catId;
            this.categoryFrom.showStatus = 1;
            this.categoryFrom.sort = 0;
           
            this.dialogVisible =true;//打开更新的窗口
        });
    },
      //删除
      remove(node, data) {
          this.$confirm(`是否确认删除【${data.name}】?`, '提示', {
             confirmButtonText: '确定',
             cancelButtonText: '取消',
             type: 'warning'
         }).then(() => {
            // 传递的数据
            let ids = [data.catId];
            // 把删除的请求提交到后台服务
            this.$http({
                url: this.$http.adornUrl("/product/category/logicDelete"),
                method: "post",
                data: this.$http.adornData(ids, false),
            }).then(({ data }) => {
                if (data && data.code === 0) {
                     this.$message({
                        message: "操作成功",
                        type: "success",
                     });
                     // 重新加载所有的菜单数据
                     this.getCatagory();

                     // 设置默认展开的父节点信息
                     this.expandKeys=[node.parent.data.catId]
                 } else {
                    this.$message.error(data.msg);
                 }
           });
        })
        .catch(() => {
          this.$message({
            type: 'info',
            message: '已取消删除'
          });
        });
        //console.log("删除",data,node)
      },

       /*这个方法什么时候触发呢？——vue生命周期的钩子方法*/
    },
    created(){
        this.getCatagory();
    }
  };
</script>

<style>

</style>
